package utils;

import converter.Point;

import java.util.ArrayList;

import java.util.List;


/**
 * Created by Сергей on 09.09.2014.
 */
public class PointsUtils {

    // to access the class creates a singleton
    private static PointsUtils instans = null;

    private PointsUtils() {
    }

    public static PointsUtils getInstansPointUtils(){

        if ( instans == null ){

            instans = new PointsUtils();

        }

        return instans;

    }

    // translate degrees to radians
    private static double toRadians ( double degree ){

        return degree*Math.PI/180;

    }


    // choose from an array, those points that fall within the rectangle
    // nePoint - the north-eastern point
    // swPoint - the south-western point

    public List<Point> selectPointsInRectangle ( List<Point> pointList, Point nePoint, Point swPoint ) {

        List <Point> pointListLokal = new ArrayList<Point>();

        for ( int i =0; i < pointList.size(); i++ ){

            Point point = pointList.get(i);

            if ( ( point.getLatitude() >= swPoint.getLatitude() ) &
                 ( point.getLatitude() <= nePoint.getLatitude() ) ){

                if ( ( point.getLongitude() >= swPoint.getLongitude() ) &
                     ( point.getLongitude() <= nePoint.getLongitude() ) ){

                pointListLokal.add( point );

                }

            }

        }

        return pointListLokal;
    }


    // choose from an array, those points that fall within the circle with a radius

    public List<Point> selectPointsInRadius( List<Point> pointList, Point center, Double radiusInDegrees ) {

        List <Point> pointListLokal = new ArrayList<Point>();

        for ( int i =0; i < pointList.size(); i ++ ){

           Point point = pointList.get(i);

           double condition = Math.pow(( point.getLongitude() - center.getLongitude() ), 2) +
                              Math.pow(( point.getLatitude() - center.getLatitude() ), 2);

            if (condition <= Math.pow( radiusInDegrees,2 )){

                pointListLokal.add(point);

            }

        }

        return pointListLokal;
    }


    public Long calculateDistanceInMeters( Point p1, Point p2 ) {

        int RADIUS_OF_THE_EATH = 6371;


        double firstLatitude = p1.getLatitude();

        double secondLatitude = p2.getLatitude();

        double firstLongitude = p1.getLongitude();

        double secondLongitude = p2.getLongitude();


        double deltaLatitude = toRadians( secondLatitude - firstLatitude );

        double deltaLongitude = toRadians( secondLongitude - firstLongitude );


        double a = Math.sqrt( Math.sin( deltaLatitude )) +

                   Math.cos( firstLatitude ) * Math.cos( secondLatitude ) *

                   Math.sqrt( Math.sin( deltaLongitude ));


        double c = 2*Math.atan2( Math.sqrt( a ), Math.sqrt( 1-a ));

        long distance = (long) (RADIUS_OF_THE_EATH * c);


        return distance;
    }

}
